//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//This is the source code for a set of wrapper functions to make calls
//to gnuplot. Gnuplot is a freely available, command-driven graphical
//display tool for Unix. It compiles and works quite well on a number
//of Unix flavours as well as other operating systems. The following
//module enables sending display requests to gnuplot through simple
//C/C++ calls.
//The module was adapted from the source code provided freely online
//by N. Devillard, Revision 2.10, September 1998.
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "gnuplot.h"
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define GP_CMD_SIZE    2048  //Maximal size of a gnuplot command
#define GP_TITLE_SIZE  80    //Maximal size of a plot title 
#define GP_EQ_SIZE     512   //Maximal size for an equation 
#define PATH_MAXNAMESZ 4096  //Maximal size of a name in the PATH 
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#ifndef P_tmpdir             //Define P_tmpdir if not defined (this is normally a POSIX symbol)
  #define P_tmpdir "."
#endif
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 *@brief Find out where a command lives in your PATH.
 *@param pname Name of the program to look for.
 *@return pointer to statically allocated character string.
 *
 * This is the C equivalent to the 'which' command in Unix. It parses
 * out your PATH environment variable to find out where a command
 * lives. The returned character string is statically allocated within
 * this function, i.e. there is no need to free it. Beware that the
 * contents of this string will change from one call to the next,
 * though (as all static variables in a function).

 * The input character string must be the name of a command without
 * prefixing path of any kind, i.e. only the command name. The returned
 * string is the path in which a command matching the same name was
 * found.

 * Examples (assuming there is a prog named 'hello' in the cwd):

 *@verbatim
 *gnuplot_get_program_path("hello") returns "."
 *gnuplot_get_program_path("ls") returns "/bin"
 *gnuplot_get_program_path("csh") returns "/usr/bin"
 *gnuplot_get_program_path("/bin/ls") returns NULL
 *@endverbatim
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
char* gnuplot_get_program_path (char* pname) {
  
  int         i, j, lg;
  char*       path;
  static char buf [PATH_MAXNAMESZ];

  /* Trivial case: try in CWD */
  sprintf(buf, "./%s", pname);
  if (access(buf, X_OK) == 0) {
    sprintf(buf, ".");
    return buf;
  }

  /* Try out in all paths given in the PATH variable */
  buf[0] = 0;
  path = getenv("PATH");
  
  if (path != NULL) {
    
    for (i = 0; path[i];) {
      for (j = i; (path[j]) && (path[j] != ':'); j++);
      
      lg = j - i;
      strncpy(buf, path + i, lg);
      
      if (lg == 0) buf[lg++] = '.';
      
      buf[lg++] = '/';
      
      strcpy(buf + lg, pname);
      
      if (access(buf, X_OK) == 0) {
        /* Found it! */
        break;
      }
      
      buf[0] = 0;
      i      = j;
      
      if (path[i] == ':') i++;
      
    }
  } 
  else fprintf(stderr, "PATH variable not set\n");

  /* If the buffer is still empty, the command was not found */
  if (buf[0] == 0) return NULL;

  /* Otherwise truncate the command name to yield path only */
  lg = strlen(buf) - 1;

  while (buf[lg] != '/') {
    buf[lg] = 0;
    lg--;
  }
  
  buf[lg] = 0;
  
  return buf;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 *@brief Opens up a gnuplot session, ready to receive commands.
 *@return Newly allocated gnuplot control structure.
 *
 * This opens up a new gnuplot session, ready for input. The struct
 * controlling a gnuplot session should remain opaque and only be
 * accessed through the provided functions.
 * The session must be closed using gnuplot_close().
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
gnuplot_ctrl* gnuplot_init (void) {
  
  gnuplot_ctrl* handle;

  if (getenv("DISPLAY") == NULL)
    fprintf(stderr, "cannot find DISPLAY variable: is it set?\n");

  if (gnuplot_get_program_path((char*) "gnuplot") == NULL) {
    fprintf(stderr, "cannot find gnuplot in your PATH");
    return NULL;
  }

  /* Structure initialization */
  handle         = (gnuplot_ctrl*) malloc(sizeof (gnuplot_ctrl));
  handle->nplots = 0;
  gnuplot_setstyle(handle, (char*) "points");
  handle->ntmp   = 0;

  handle->gnucmd = popen("gnuplot", "w");
  
  if (handle->gnucmd == NULL) {
    fprintf(stderr, "error starting gnuplot\n");
    free(handle);
    return NULL;
  }
  
  return handle;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 *@brief Closes a gnuplot session previously opened by gnuplot_init()
 *@param handle Gnuplot session control handle.
 *@return void
 *
 * Kills the child PID and deletes all opened temporary files.
 * It is mandatory to call this function to close the handle, otherwise
 * temporary files are not cleaned and child process might survive.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_close (gnuplot_ctrl* handle) {
  
  int i;

  if (pclose(handle->gnucmd) == -1) {
    fprintf(stderr, "problem closing communication to gnuplot\n");
    return;
  }
  
  if (handle->ntmp) {
    for (i = 0; i < handle->ntmp; i++)
      remove(handle->to_delete[i]);
  }
  
  free(handle);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sends a command to an active gnuplot session.
 * @param handle Gnuplot session control handle
 * @param cmd Command to send, same as a printf statement.
 *
 * This sends a string to an active gnuplot session, to be executed.
 * There is strictly no way to know if the command has been
 * successfully executed or not.
 * The command syntax is the same as printf.
 *
 * Examples:
 *
 * @code
 * gnuplot_cmd(g, "plot %d*x", 23.0);
 * gnuplot_cmd(g, "plot %g * cos(%g * x)", 32.0, -3.0);
 * @endcode
 *
 * Since the communication to the gnuplot process is run through
 * a standard Unix pipe, it is only unidirectional. This means that
 * it is not possible for this interface to query an error status
 * back from gnuplot.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_cmd (gnuplot_ctrl* handle, char* cmd, ...) {
  
  va_list ap;
  char    local_cmd [GP_CMD_SIZE];

  va_start(ap, cmd);
  vsprintf(local_cmd, cmd, ap);
  va_end(ap);

  strcat(local_cmd, "\n");

  fputs(local_cmd, handle->gnucmd);
  fflush(handle->gnucmd);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Change the plotting style of a gnuplot session.
 * @param h Gnuplot session control handle
 * @param plot_style Plotting-style to use (character string)
 * @return void
 *
 * The provided plotting style is a character string. It must be one of
 * the following:
 *
 * - lines
 * - points
 * - linespoints
 * - impulses
 * - dots
 * - steps
 * - errorbars
 * - boxes
 * - boxeserrorbars
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_setstyle (gnuplot_ctrl* h, const char* plot_style) {
  
//  if (strcmp(plot_style, "lines")       &&
//      strcmp(plot_style, "points")      &&
//      strcmp(plot_style, "linespoints") &&
//      strcmp(plot_style, "impulses")    &&
//      strcmp(plot_style, "dots")        &&
//      strcmp(plot_style, "steps")       &&
//      strcmp(plot_style, "errorbars")   &&
//      strcmp(plot_style, "boxes")       &&
//      strcmp(plot_style, "boxerrorbars")) {
//    fprintf(stderr, "warning: unknown requested style: using points\n");
//    strcpy(h->pstyle, "points");
//  } 
//  else strcpy(h->pstyle, plot_style);
  
  strcpy(h->pstyle, plot_style);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the title of a gnuplot session.
 * @param h Gnuplot session control handle.
 * @param label Character string to use for title.
 * @return void
 *
 * Sets the title for a gnuplot session.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_title (gnuplot_ctrl* h, char* label) {
  
  char cmd [GP_CMD_SIZE];

  sprintf(cmd, "set title \"%s\"", label);
  gnuplot_cmd(h, cmd);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the x label of a gnuplot session.
 * @param h Gnuplot session control handle.
 * @param label Character string to use for X label.
 * @return void
 *
 * Sets the x label for a gnuplot session.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_xlabel (gnuplot_ctrl* h, const char* label, const char* parameters) {
  
  char cmd [GP_CMD_SIZE];

  sprintf(cmd, "set xlabel \"%s\" %s", label, parameters);
  gnuplot_cmd(h, cmd);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the y label of a gnuplot session.
 * @param h Gnuplot session control handle
 * @param label Character string to use for Y label.
 * @return void
 *
 * Sets the y label for a gnuplot session.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_ylabel (gnuplot_ctrl* h, const char* label, const char* parameters) {
  
  char cmd [GP_CMD_SIZE];

  sprintf(cmd, "set ylabel \"%s\" %s", label, parameters);
  gnuplot_cmd(h, cmd);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the minimum and maximum y values for a gnuplot session
 * @param h Gnuplot session control handle
 * @param lower the minimum y value
 * @param upper the maximum y value
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_yrange (gnuplot_ctrl* h, int lower, int upper) {
  
  std::stringstream cmd;
  
  cmd << "set yrange [" << lower << ":" << upper << "]";
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the minimum and maximum y values for a gnuplot session
 * @param h Gnuplot session control handle
 * @param lower the minimum y value
 * @param upper the maximum y value
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_yrange (gnuplot_ctrl* h, float lower, float upper) {
  
  std::stringstream cmd;
  
  cmd << "set yrange [" << lower << ":" << upper << "]";
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the minimum and maximum y values for a gnuplot session
 * @param h Gnuplot session control handle
 * @param lower the minimum y value
 * @param upper the maximum y value
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_yrange (gnuplot_ctrl* h, double lower, double upper) {
  
  std::stringstream cmd;
  
  cmd << "set yrange [" << lower << ":" << upper << "]";
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the minimum and maximum x values for a gnuplot session
 * @param h Gnuplot session control handle
 * @param lower the minimum y value
 * @param upper the maximum y value
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_xrange (gnuplot_ctrl* h, int lower, int upper) {
  
  std::stringstream cmd;
  
  cmd << "set xrange [" << lower << ":" << upper << "]";
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the minimum and maximum x values for a gnuplot session
 * @param h Gnuplot session control handle
 * @param lower the minimum y value
 * @param upper the maximum y value
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_xrange (gnuplot_ctrl* h, float lower, float upper) {
  
  std::stringstream cmd;
  
  cmd << "set xrange [" << lower << ":" << upper << "]";
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Sets the minimum and maximum x values for a gnuplot session
 * @param h Gnuplot session control handle
 * @param lower the minimum y value
 * @param upper the maximum y value
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_set_xrange (gnuplot_ctrl* h, double lower, double upper) {
  
  std::stringstream cmd;
  
  cmd << "set xrange [" << lower << ":" << upper << "]";
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Resets a gnuplot session (next plot will erase previous ones).
 * @param h Gnuplot session control handle.
 * @return void
 *
 * Resets a gnuplot session, i.e. the next plot will erase all previous
 * ones.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_resetplot (gnuplot_ctrl* h) {

  int i;

  if (h->ntmp) {
    for (i = 0; i < h->ntmp; i++)
      remove(h->to_delete[i]);
  }
  
  h->ntmp   = 0;
  h->nplots = 0;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Saves the current Gnuplot session as a postscript
 * @param h Gnuplot session control handle
 * @param filename the name of the file the plot will be saved as
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_saveplotPS (gnuplot_ctrl* h, char* filename, int sizeLetter, int sizeX, int sizeY) {
  
  std::stringstream cmd;
  std::stringstream parameters;
  
  cmd << "set output \"" << filename << ".ps\"";
  parameters << "set terminal postscript size " << (float)((float)sizeX/(float)100) << "," << (float)((float)sizeY/(float)100) << " enhanced font 'calibri," << sizeLetter << "'";
  
  gnuplot_cmd(h, (char*) parameters.str().c_str());
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Saves the current Gnuplot session as a pdf
 * @param h Gnuplot session control handle
 * @param filename the name of the file the plot will be saved as
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_saveplotPDF (gnuplot_ctrl* h, char* filename, int sizeLetter, int sizeX, int sizeY) {
  
  std::stringstream cmd;
  std::stringstream parameters;
  
  cmd << "set output \"" << filename << ".pdf\"";
  parameters << "set terminal pdf font 'calibri, 8' size " << sizeX << ", " << sizeY << " enhanced";
  
  gnuplot_cmd(h, (char*) parameters.str().c_str());
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Saves the current Gnuplot session as a PNG
 * @param h Gnuplot session control handle
 * @param filename the name of the file the plot will be saved as
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_saveplotPNG (gnuplot_ctrl* h, char* filename, int sizeLetter, int sizeX, int sizeY) {
  
  std::stringstream cmd;
  std::stringstream parameters;
  
  cmd << "set output \"" << filename << ".png\"";
  parameters << "set terminal png font 'FreeMono-Bold, "<< sizeLetter << "' size " << sizeX << ", " << sizeY << " enhanced";
  
  gnuplot_cmd(h, (char*) parameters.str().c_str());
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Saves the current Gnuplot session as a EPS
 * @param h Gnuplot session control handle
 * @param filename the name of the file the plot will be saved as
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_saveplotEPS (gnuplot_ctrl* h, char* filename, int sizeLetter, int sizeX, int sizeY) {
  
  std::stringstream cmd;
  std::stringstream parameters;
  
  cmd << "set output \"" << filename << ".eps\"";
  parameters << "set terminal epslatex 8 font 'FreeMono-Bold, "<< sizeLetter << "' size " << sizeX << ", " << sizeY;
  
  gnuplot_cmd(h, (char*) parameters.str().c_str());
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Saves the current Gnuplot session as a gif
 * @param h Gnuplot session control handle
 * @param filename the name of the file the plot will be saved as
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_saveplotGIF (gnuplot_ctrl* h, char* filename, int sizeLetter, int sizeX, int sizeY) {
  
  std::stringstream cmd;
  
  cmd << "set output \"" << filename << ".gif\" size 1200,600 enhanced";
  
  gnuplot_cmd(h, (char*) "set term gif");
  gnuplot_cmd(h, (char*) cmd.str().c_str());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plots a 2d graph from a list of ints
 * @param handle Gnuplot session control handle.
 * @param d Array of ints.
 * @param n Number of values in the passed array.
 * @param title Title of the plot.
 * @return void
 *
 * Plots out a 2d graph from a list of ints. The x-coordinate is the
 * index of the float in the list, the y coordinate is the int in
 * the list.
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl *h;
 * int d[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * d[i] = (int)(i*i);
 * }
 * gnuplot_plot_x(h, d, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_x (gnuplot_ctrl* handle, int* d, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd [GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || d == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;
  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%d\n", d[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  strcpy(cmd, "plot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name, title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plots a 2d graph from a list of floats
 * @param handle Gnuplot session control handle.
 * @param d Array of floats.
 * @param n Number of values in the passed array.
 * @param title Title of the plot.
 * @return void
 *
 * Plots out a 2d graph from a list of floats. The x-coordinate is the
 * index of the float in the list, the y coordinate is the float in
 * the list.
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl *h;
 * float d[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * d[i] = (float)(i*i);
 * }
 * gnuplot_plot_x(h, d, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_x (gnuplot_ctrl* handle, float* d, int n, char* title) {
  
  int  i,  tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || d == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;
  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%g\n", d[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  strcpy(cmd, "plot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name, title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plots a 2d graph from a list of doubles
 * @param handle Gnuplot session control handle.
 * @param d Array of doubles.
 * @param n Number of values in the passed array.
 * @param title Title of the plot.
 * @return void
 *
 * Plots out a 2d graph from a list of double. The x-coordinate is the
 * index of the double in the list, the y coordinate is the double in
 * the list.
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl *h;
 * double d[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * d[i] = (double)(i*i);
 * }
 * gnuplot_plot_x(h, d, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_x (gnuplot_ctrl* handle, double* d, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || d == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;
  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%f\n", d[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
  }
  close(tmpfd);

  strcpy(cmd, "plot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name, title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  
//  strcpy(cmd, "replot");
//
//  if (title == NULL)
//    sprintf(line, "%s \"%s\" smooth bezier with %s", cmd, name, handle->pstyle);
//  else
//    sprintf(line, "%s \"%s\" smooth bezier title \"%s\" with %s", cmd, name, title, handle->pstyle);
//
//  /* send command to gnuplot */
//  gnuplot_cmd(handle, line);
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Replots a 2d graph from a list of ints
 * @param handle Gnuplot session control handle.
 * @param d Array of ints.
 * @param n Number of values in the passed array.
 * @param title Title of the plot.
 * @return void
 *
 * Replots out a 2d graph from a list of ints. The x-coordinate is the
 * index of the float in the list, the y coordinate is the int in
 * the list.
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl *h;
 * int d[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * d[i] = (int)(i*i);
 * }
 * gnuplot_replot_x(h, d, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_replot_x (gnuplot_ctrl* handle, int* d, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd [GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || d == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;
  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%d\n", d[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  strcpy(cmd, "replot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name, title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Replots a 2d graph from a list of floats
 * @param handle Gnuplot session control handle.
 * @param d Array of floats.
 * @param n Number of values in the passed array.
 * @param title Title of the plot.
 * @return void
 *
 * Replots out a 2d graph from a list of floats. The x-coordinate is the
 * index of the float in the list, the y coordinate is the float in
 * the list.
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl *h;
 * float d[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * d[i] = (float)(i*i);
 * }
 * gnuplot_replot_x(h, d, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_replot_x (gnuplot_ctrl* handle, float* d, int n, char* title) {
  
  int  i,  tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || d == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;
  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%g\n", d[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  strcpy(cmd, "replot");
  sprintf(line, "%s \"%s\" ti \"%s\" with %s", cmd, name, title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Replots a 2d graph from a list of doubles
 * @param handle Gnuplot session control handle.
 * @param d Array of doubles.
 * @param n Number of values in the passed array.
 * @param title Title of the plot.
 * @return void
 *
 * Replots out a 2d graph from a list of double. The x-coordinate is the
 * index of the double in the list, the y coordinate is the double in
 * the list.
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl *h;
 * double d[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * d[i] = (double)(i*i);
 * }
 * gnuplot_replot_x(h, d, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_replot_x (gnuplot_ctrl* handle, double* d, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || d == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;
  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%f\n", d[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
  }
  close(tmpfd);

  strcpy(cmd, "replot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name, title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  
//  strcpy(cmd, "replot");
//
//  if (title == NULL)
//    sprintf(line, "%s \"%s\" smooth bezier with %s", cmd, name, handle->pstyle);
//  else
//    sprintf(line, "%s \"%s\" smooth bezier title \"%s\" with %s", cmd, name, title, handle->pstyle);
//
//  /* send command to gnuplot */
//  gnuplot_cmd(handle, line);
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plot a 2d graph from a list of points.
 * @param handle Gnuplot session control handle.
 * @param x Pointer to a list of x coordinates.
 * @param y Pointer to a list of y coordinates.
 * @param n Number of doubles in x (assumed the same as in y).
 * @param title Title of the plot.
 * @return void
 *
 * Plots out a 2d graph from a list of points. Provide points through a list
 * of x and a list of y coordinates. Both provided arrays are assumed to
 * contain the same number of values.
 *
 * @code
 * gnuplot_ctrl *h;
 * int x[50];
 * int y[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * x[i] = (int)(i)/10.0;
 * y[i] = x[i] * x[i];
 * }
 * gnuplot_plot_xy(h, x, y, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_xy (gnuplot_ctrl* handle, int* x, int* y, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || x == NULL || y == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }
  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;

  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%d %d\n", x[i], y[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_xy");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  if (handle->nplots > 0)
    strcpy(cmd, "replot");
  else
    strcpy(cmd, "plot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name,
    title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);

  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plot a 2d graph from a list of points.
 * @param handle Gnuplot session control handle.
 * @param x Pointer to a list of x coordinates.
 * @param y Pointer to a list of y coordinates.
 * @param n Number of doubles in x (assumed the same as in y).
 * @param title Title of the plot.
 * @return void
 *
 * Plots out a 2d graph from a list of points. Provide points through a list
 * of x and a list of y coordinates. Both provided arrays are assumed to
 * contain the same number of values.
 *
 * @code
 * gnuplot_ctrl *h;
 * float x[50];
 * float y[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * x[i] = (float)(i)/10.0;
 * y[i] = x[i] * x[i];
 * }
 * gnuplot_plot_xy(h, x, y, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_xy (gnuplot_ctrl* handle, float* x, float* y, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || x == NULL || y == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }
  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;

  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%g %g\n", x[i], y[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_xy");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  if (handle->nplots > 0)
    strcpy(cmd, "replot");
  else
    strcpy(cmd, "plot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name,
    title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);

  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plot a 2d graph from a list of points.
 * @param handle Gnuplot session control handle.
 * @param x Pointer to a list of x coordinates.
 * @param y Pointer to a list of y coordinates.
 * @param n Number of doubles in x (assumed the same as in y).
 * @param title Title of the plot.
 * @return void
 *
 * Plots out a 2d graph from a list of points. Provide points through a list
 * of x and a list of y coordinates. Both provided arrays are assumed to
 * contain the same number of values.
 *
 * @code
 * gnuplot_ctrl *h;
 * double x[50];
 * double y[50];
 * int i;
 *
 * h = gnuplot_init();
 * for (i=0; i<50; i++) {
 * x[i] = (float)(i)/10.0;
 * y[i] = x[i] * x[i];
 * }
 * gnuplot_plot_xy(h, x, y, 50, "parabola");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_xy (gnuplot_ctrl* handle, double* x, double* y, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || x == NULL || y == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }
  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;

  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%f %f\n", x[i], y[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_xy");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  if (handle->nplots > 0)
    strcpy(cmd, "replot");
  else
    strcpy(cmd, "plot");

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name,
    title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);

  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Open a new session, plot a signal, close the session.
 * @param title Plot title
 * @param style Plot style
 * @param label_x Label for X
 * @param label_y Label for Y
 * @param x Array of X coordinates
 * @param y Array of Y coordinates (can be NULL)
 * @param n Number of values in x and y.
 * @return
 *
 * This function opens a new gnuplot session, plots the provided
 * signal as an X or XY signal depending on a provided y, waits for
 * a carriage return on stdin and closes the session.
 *
 * It is Ok to provide an empty title, empty style, or empty labels for
 * X and Y. Defaults are provided in this case.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_once (char* title, char* style, char* label_x, char* label_y, int* x, int* y, int n) {
  
  gnuplot_ctrl* handle;

  if (x == NULL || n < 1)
    return;

  if ((handle = gnuplot_init()) == NULL)
    return;

  if (style != NULL)
    gnuplot_setstyle(handle, style);
  else
    gnuplot_setstyle(handle, (char*) "lines");

  if (label_x != NULL)
    gnuplot_set_xlabel(handle, label_x, "");
  else
    gnuplot_set_xlabel(handle, (char*) "X", "");

  if (label_y != NULL)
    gnuplot_set_ylabel(handle, label_y, "");
  else
    gnuplot_set_ylabel(handle, (char*) "Y", "");

  if (y == NULL)
    gnuplot_plot_x(handle, x, n, title);
  else
    gnuplot_plot_xy(handle, x, y, n, title);

  printf("press ENTER to continue\n");
  while (getchar() != '\n') {
  }
  
  gnuplot_close(handle);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Open a new session, plot a signal, close the session.
 * @param title Plot title
 * @param style Plot style
 * @param label_x Label for X
 * @param label_y Label for Y
 * @param x Array of X coordinates
 * @param y Array of Y coordinates (can be NULL)
 * @param n Number of values in x and y.
 * @return
 *
 * This function opens a new gnuplot session, plots the provided
 * signal as an X or XY signal depending on a provided y, waits for
 * a carriage return on stdin and closes the session.
 *
 * It is Ok to provide an empty title, empty style, or empty labels for
 * X and Y. Defaults are provided in this case.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_once (char* title, char* style, char* label_x, char* label_y, float* x, float* y, int n) {
  
  gnuplot_ctrl* handle;

  if (x == NULL || n < 1)
    return;

  if ((handle = gnuplot_init()) == NULL)
    return;

  if (style != NULL)
    gnuplot_setstyle(handle, style);
  else
    gnuplot_setstyle(handle, (char*) "lines");

  if (label_x != NULL)
    gnuplot_set_xlabel(handle, label_x, "");
  else
    gnuplot_set_xlabel(handle, (char*) "X", "");

  if (label_y != NULL)
    gnuplot_set_ylabel(handle, label_y, "");
  else
    gnuplot_set_ylabel(handle, (char*) "Y", "");

  if (y == NULL)
    gnuplot_plot_x(handle, x, n, title);
  else
    gnuplot_plot_xy(handle, x, y, n, title);

  printf("press ENTER to continue\n");
  while (getchar() != '\n') {
  }
  gnuplot_close(handle);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Open a new session, plot a signal, close the session.
 * @param title Plot title
 * @param style Plot style
 * @param label_x Label for X
 * @param label_y Label for Y
 * @param x Array of X coordinates
 * @param y Array of Y coordinates (can be NULL)
 * @param n Number of values in x and y.
 * @return
 *
 * This function opens a new gnuplot session, plots the provided
 * signal as an X or XY signal depending on a provided y, waits for
 * a carriage return on stdin and closes the session.
 *
 * It is Ok to provide an empty title, empty style, or empty labels for
 * X and Y. Defaults are provided in this case.
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_once (char* title, char* style, char* label_x, char* label_y, double* x, double* y, int n) {
  
  gnuplot_ctrl* handle;

  if (x == NULL || n < 1)
    return;

  if ((handle = gnuplot_init()) == NULL)
    return;

  if (style != NULL)
    gnuplot_setstyle(handle, style);
  else
    gnuplot_setstyle(handle, (char*) "lines");

  if (label_x != NULL)
    gnuplot_set_xlabel(handle, label_x, "");
  else
    gnuplot_set_xlabel(handle, (char*) "X", "");

  if (label_y != NULL)
    gnuplot_set_ylabel(handle, label_y, "");
  else
    gnuplot_set_ylabel(handle, (char*) "Y", "");

  if (y == NULL)
    gnuplot_plot_x(handle, x, n, title);
  else
    gnuplot_plot_xy(handle, x, y, n, title);

  printf("press ENTER to continue\n");
  while (getchar() != '\n') {
  }
  
  gnuplot_close(handle);
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plot a slope on a gnuplot session.
 * @param handle Gnuplot session control handle.
 * @param a Slope.
 * @param b Intercept.
 * @param title Title of the plot.
 * @return void
 *
 * Plot a slope on a gnuplot session. The provided slope has an
 * equation of the form y=ax+b
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl * h;
 * float a, b;
 *
 * h = gnuplot_init();
 * gnuplot_plot_slope(h, 1.0, 0.0, "unity slope");
 * sleep(2);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_slope (gnuplot_ctrl* handle, float a, float b, char* title) {

  char stitle[GP_TITLE_SIZE], cmd[GP_CMD_SIZE];

  if (title == NULL)
    strcpy(stitle, "no title");
  else
    strcpy(stitle, title);

  if (handle->nplots > 0)
    sprintf(cmd, "replot %g * x + %g title \"%s\" with %s",
    a, b, title, handle->pstyle);
  else
    sprintf(cmd, "plot %g * x + %g title \"%s\" with %s",
    a, b, title, handle->pstyle);

  gnuplot_cmd(handle, cmd);
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plot a curve of given equation y=f(x).
 * @param h Gnuplot session control handle.
 * @param equation Equation to plot.
 * @param title Title of the plot.
 * @return void
 *
 * Plots out a curve of given equation. The general form of the
 * equation is y=f(x), you only provide the f(x) side of the equation.
 *
 * Example:
 *
 * @code
 * gnuplot_ctrl *h;
 * char eq[80];
 *
 * h = gnuplot_init();
 * strcpy(eq, "sin(x) * cos(2*x)");
 * gnuplot_plot_equation(h, eq, "sine wave", normal);
 * gnuplot_close(h);
 * @endcode
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_equation (gnuplot_ctrl* h, char* equation, char* title) {

  char cmd[GP_CMD_SIZE], plot_str[GP_EQ_SIZE], title_str[GP_TITLE_SIZE];

  if (title == NULL)
    strcpy(title_str, "no title");
  else
    strcpy(title_str, title);

  if (h->nplots > 0)
    strcpy(plot_str, "replot");
  else
    strcpy(plot_str, "plot");

  sprintf(cmd, "%s %s title \"%s\" with %s",
    plot_str, equation, title_str, h->pstyle);
  gnuplot_cmd(h, cmd);
  h->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_histogram (gnuplot_ctrl* handle, double* d, int n, int div, char* title) {
  
  int  i, tmpfd, tmpfdfit;
  char name[128], namefit[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || d == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(namefit, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfdfit = mkstemp(namefit)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }

  double max = d[0], min = d[0];
  int    fitValue[div];

  for (i = 0; i < div; i++) 
    fitValue[i] = 0;

  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;
  /* Write data to this file */
  for (i = 0; i < n; i++) {
    
    if (d[i] > max) max = d[i];
    if (d[i] < min) min = d[i];
    
    sprintf(line, "%f\n", d[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
    
  }
  close(tmpfd);
  
  float width = ((max-min)/(float)div);
  
  //printf("Width: %f\n", width);
    
  for (i = 0; i < n; i++) { 
    //printf("fitValue[%d]: %d\n", (int)((d[i]-min)/(float)width), fitValue[(int)((d[i]-min)/(float)width)]);
    fitValue[(int)((d[i]-min)/(float)width)]++;
  }
  
  for (i = 0; i < div; i++) {
    
    sprintf(line, "%f %d\n", min + width*(i + 1), fitValue[i]);
    //printf("%f %d\n", min + width*(i + 1), fitValue[i]);
    int writeRet = write(tmpfdfit, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_x");
    
  }
  
  close(tmpfdfit);

  sprintf(cmd, "n=%d\0", div);
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "max=%f\0", max);
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "min=%f\0", min);
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "width=(max-min)/n\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "hist(x,width)=width*floor(x/width)+width/2.0\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "set xrange [min:max]\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "set yrange [0:]\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "set offset graph 0.05,0.05,0.05,0.0\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "set xtics min,(max-min)/5,max\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "set boxwidth width*0.9\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "set style fill solid 0.5\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "set tics out nomirror\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "PI=3.14; s=1; m=1; a=1;\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "gauss(x) = a/(2*PI*s**2)**0.5*exp(-(x-m)**2/(2*s**2))\0");
  gnuplot_cmd(handle, cmd);

  sprintf(cmd, "fit gauss(x) \"%s\" using 1:2 via s, m, a\0", namefit);
  gnuplot_cmd(handle, cmd);

  strcpy(cmd, "plot");
//  if (title == NULL)
//    sprintf(line, "%s \"%s\" u (hist($1,width)):(1.0) smooth freq w boxes lc rgb \"black\"", cmd, name);
//  else
//    sprintf(line, "%s \"%s\" u (hist($1,width)):(1.0) smooth freq w boxes lc rgb \"black\" title \"%s\"", cmd, name, title);
//
//  /* send command to gnuplot */
//  gnuplot_cmd(handle, line);
//  
//  strcpy(cmd, "replot");

//  sprintf(cmd, "set style line 1 lt 1 lw 3 pt 3 linecolor rgb \"red\"\0");
//  gnuplot_cmd(handle, cmd);
//
  sprintf(line, "%s \"%s\" using 1:2, gauss(x) title \"%s\"", cmd, namefit, title);
  /* send command to gnuplot */
  gnuplot_cmd(handle, line);

  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plots a 3D scatter point from 3 arrays of ints
 * @param handle Gnuplot session handle
 * @param x array of ints
 * @param y array of ints
 * @param z array of ints
 * @param n number of ints in each array x, y, and z
 * @param title the title for the plot
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_xyz(gnuplot_ctrl* handle, int* x, int* y, int* z, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || x == NULL || y == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }
  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;

  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%d %d %d\n", x[i], y[i], z[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_xyz");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  if (handle->nplots > 0)
    strcpy(cmd, "replot");
  else {
    strcpy(cmd, "dgrid3d");
    strcpy(cmd, "splot");
  }

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name,
    title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plots a 3D scatter point from 3 arrays of floats
 * @param handle Gnuplot session handle
 * @param x array of floats
 * @param y array of floats
 * @param z array of floats
 * @param n number of floats in each array x, y, and z
 * @param title the title for the plot
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_xyz (gnuplot_ctrl* handle, float* x, float* y, float* z, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || x == NULL || y == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }
  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;

  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%g %g %g\n", x[i], y[i], z[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_xyz");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  if (handle->nplots > 0)
    strcpy(cmd, "replot");
  else {
    strcpy(cmd, "dgrid3d");
    strcpy(cmd, "splot");
  }

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name,
    title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
/**
 * @brief Plots a 3D scatter point from 3 arrays of doubles
 * @param handle Gnuplot session handle
 * @param x array of doubles
 * @param y array of doubles
 * @param z array of doubles
 * @param n number of doubles in each array x, y, and z
 * @param title the title for the plot
 */
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void gnuplot_plot_xyz(gnuplot_ctrl* handle, double* x, double* y, double* z, int n, char* title) {
  
  int  i, tmpfd;
  char name[128], cmd[GP_CMD_SIZE], line[GP_CMD_SIZE];

  if (handle == NULL || x == NULL || y == NULL || (n < 1)) return;

  /* Open one more temporary file? */
  if (handle->ntmp == GP_MAX_TMP_FILES - 1) {
    fprintf(stderr,
      "maximum # of temporary files reached (%d): cannot open more",
      GP_MAX_TMP_FILES);
    return;
  }

  /* Open temporary file for output */
  sprintf(name, "%s/gnuplot-i-XXXXXX", P_tmpdir);
  if ((tmpfd = mkstemp(name)) == -1) {
    fprintf(stderr, "cannot create temporary file: exiting plot");
    return;
  }
  /* Store file name in array for future deletion */
  strcpy(handle->to_delete[handle->ntmp], name);
  handle->ntmp++;

  /* Write data to this file */
  for (i = 0; i < n; i++) {
    sprintf(line, "%f %f %f\n", x[i], y[i], z[i]);
    int writeRet = write(tmpfd, line, strlen(line));
    if (writeRet == -1)
      printf("Error writing data to a file in gnuplot_xyz");
  }
  close(tmpfd);

  /* Command to be sent to gnuplot */
  if (handle->nplots > 0)
    strcpy(cmd, "replot");
  else {
    strcpy(cmd, "dgrid3d");
    strcpy(cmd, "splot");
  }

  if (title == NULL)
    sprintf(line, "%s \"%s\" with %s", cmd, name, handle->pstyle);
  else
    sprintf(line, "%s \"%s\" title \"%s\" with %s", cmd, name,
    title, handle->pstyle);

  /* send command to gnuplot */
  gnuplot_cmd(handle, line);
  handle->nplots++;
  
  return;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
